/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * SimulationPaintFrame.java
 *
 * Created on 9 Ιουλ 2009, 12:08:14 μμ
 */
package gui;

import base.node.WSNode;
import java.awt.event.MouseEvent;
import simulation.GUIOptionManager;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import simulation.SimulationManager;

/**
 * The frame used to graphically present the simulation process
 * @author Arvanitis Ioannis
 */
public class SimulationPaintFrame extends javax.swing.JFrame implements Runnable {

    private int terrain_width;
    private int terrain_height;
    private static Timer timer;
    private int simTime;
    private Thread runner;

    /**
     * Creates new form TerrainPaintFrame
     * @param w Width (in cells) of canvas
     * @param h Height (in cells) of canvas
     */
    public SimulationPaintFrame(int w, int h) {
        this.terrain_width = w;
        this.terrain_height = h;
        runner = new Thread(this);
        runner.start();
    }

    public void run() {
        setTitle("Simulation");
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Dimension screensize = toolkit.getScreenSize();
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        //----------------------------------------------------------------------
        final SimulationCanvasPanel canvas = new SimulationCanvasPanel(terrain_width, terrain_height);
        JPanel actions = new JPanel();
        final JPanel details = new JPanel();

        final JButton start = new JButton("Start");
        final JButton pause = new JButton("Pause");
        final JButton stop = new JButton("Stop");
        JButton exit = new JButton("Exit");
        pause.setEnabled(false);
        stop.setEnabled(false);
        final JCheckBox checkbox = new JCheckBox("Show categories");
        checkbox.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        final JLabel current = new JLabel();
        current.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

        JLabel id = new JLabel("ID :");
        final JLabel id_val = new JLabel();
        JLabel coordinates = new JLabel("Coordinations :");
        final JLabel coordinates_val = new JLabel();
        JLabel energy = new JLabel("Energy :");
        final JLabel energy_val = new JLabel();
        JLabel category = new JLabel("Category :");
        final JLabel category_val = new JLabel();
        JLabel nodesInCategory = new JLabel("Total nodes in category :");
        final JLabel nodesInCategory_val = new JLabel();
        JLabel mobile = new JLabel("Mobility :");
        final JLabel mobile_val = new JLabel();
        JLabel antRadiatedPower = new JLabel("Antenna's radiated power :");
        final JLabel antRadiatedPower_val = new JLabel();
        JLabel antActivationThreshold = new JLabel("Antenna's activation threshold :");
        final JLabel antActivationThreshold_val = new JLabel();


        start.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                start.setEnabled(false);
                pause.setEnabled(true);
                stop.setEnabled(true);

                SimulationManager.start();

                simTime = GUIOptionManager.getSimTotalTimeInSec();
                timer = new Timer(1000, new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        simTime -= 1;
                        setTitle("Simulation in progress... " + simTime + " sec remaining");
                        repaint();
                        if (simTime == 0) {
                            stop.doClick();
                        }
                    }
                });
                timer.start(); //start the simulation timer
                SimulationManager.simulate(); //start the simulation
            }
        });

        pause.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                start.setEnabled(false);
                pause.setEnabled(true);
                stop.setEnabled(true);
                if (timer.isRunning()) {
                    timer.stop();
                    pause.setText("Unpause");
                    WSNode[] wsn = SimulationManager.getNode();
                    for (int i = 0; i < wsn.length; i++) {
                        wsn[i].getTimer4IdleConsumption().stop();
                        wsn[i].getTimer4InternalOperations().stop();
                    }
                    setTitle("Simulation paused... " + simTime + " sec remaining");
                } else {
                    timer.start();
                    pause.setText("Pause");
                    WSNode[] wsn = SimulationManager.getNode();
                    for (int i = 0; i < wsn.length; i++) {
                        wsn[i].getTimer4IdleConsumption().start();
                        wsn[i].getTimer4InternalOperations().start();
                    }
                    setTitle("Simulation in progress... " + simTime + " sec remaining");
                }
            }
        });

        stop.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                start.setEnabled(true);
                pause.setEnabled(false);
                stop.setEnabled(false);
                timer.stop();
                WSNode[] wsn = SimulationManager.getNode();
                for (int i = 0; i < wsn.length; i++) {
                    wsn[i].getTimer4IdleConsumption().stop();
                    wsn[i].getTimer4InternalOperations().stop();
                }
                setTitle("Simulation stopped... " + simTime + " sec remaining");
                SimulationManager.stop();
            }
        });

        exit.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                timer.stop();
                WSNode[] wsn = SimulationManager.getNode();
                for (int i = 0; i < wsn.length; i++) {
                    wsn[i].getTimer4IdleConsumption().stop();
                    wsn[i].getTimer4InternalOperations().stop();
                }
                SimulationManager.stop();
                dispose();
            }
        });

        checkbox.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (checkbox.isSelected()) {
                    SimulationCanvasPanel.setCategoriesShown(true);
                } else {
                    SimulationCanvasPanel.setCategoriesShown(false);
                }
                repaint();
            }
        });

        canvas.addMouseListener(new MouseListener() {

            /**
             * Mouse was clicked in the canvas area
             * @param e MouseEvent
             */
            public void mouseClicked(MouseEvent e) {
                Point p = e.getPoint();
                int currentNodeId;
                if (canvas.inCanvas(p)) {
                    p = canvas.findCurrentPosition(p);
                    currentNodeId = canvas.findCurrentNode(p);
                    if (currentNodeId > 0) {
                        if (e.getClickCount() == 1) {
                            WSNode node = SimulationManager.getNode(currentNodeId - 1);
                            int cat = Integer.parseInt(GUIOptionManager.getNodes().get(currentNodeId - 1).getInfo());
                            id_val.setText("" + currentNodeId);
                            coordinates_val.setText(node.getNodeInfo().getPosition().x + "," + node.getNodeInfo().getPosition().y);
                            energy_val.setText(node.getNodeInfo().getEnergy() + " mWh");
                            category_val.setText("" + cat);
                            nodesInCategory_val.setText("" + GUIOptionManager.getNodeArchPerCategory().get(cat - 1).getNumberOfNodes());
                            if (GUIOptionManager.getNodeArchPerCategory().get(cat - 1).isMobile()) {
                                mobile_val.setText("enabled");
                            } else {
                                mobile_val.setText("disabled");
                            }
                            antRadiatedPower_val.setText(node.getNodeInfo().getAntennaRadPow() + " dBm");
                            antActivationThreshold_val.setText(node.getNodeInfo().getAntennaThres() + " dBm");
                            JOptionPane.showMessageDialog(null, details, "Properties", JOptionPane.INFORMATION_MESSAGE);
                        }
                    }
                }
            }

            /**
             * Mouse was pressed in the canvas area
             * @param e MouseEvent
             */
            public void mousePressed(MouseEvent e) {
                //        throw new UnsupportedOperationException("Not supported yet.");
            }

            /**
             * Mouse was released in the canvas area
             * @param e MouseEvent
             */
            public void mouseReleased(MouseEvent e) {
                //        throw new UnsupportedOperationException("Not supported yet.");
            }

            /**
             * Mouse entered the canvas area
             * @param e MouseEvent
             */
            public void mouseEntered(MouseEvent e) {
                canvas.setCursor(new Cursor(Cursor.HAND_CURSOR));
            }

            /**
             * Mouse exited the canvas area
             * @param e MouseEvent
             */
            public void mouseExited(MouseEvent e) {
                canvas.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });

        canvas.addMouseMotionListener(new MouseMotionListener() {

            /**
             * Mouse was dragged in the canvas area
             * @param e MouseEvent
             */
            public void mouseDragged(MouseEvent e) {
                mouseMoved(e);
            }

            /**
             * Mouse was moved in the canvas area
             * @param e MouseEvent
             */
            public void mouseMoved(MouseEvent e) {
                Point p = e.getPoint();
                int currentNodeId;
                if (canvas.inCanvas(p)) {
                    p = canvas.findCurrentPosition(p);
                    current.setText(p.x + "," + p.y);
                    currentNodeId = canvas.findCurrentNode(p);
                    if (currentNodeId > 0) {
                        canvas.setToolTipText("node " + currentNodeId);
                    } else {
                        canvas.setToolTipText(null);
                    }
                } else {
                    current.setText(null);
                    canvas.setToolTipText(null);
                }
                repaint();
            }
        });


        actions.setLayout(new GridLayout(1, 6));
        details.setLayout(new GridLayout(8, 2));
        actions.add(start);
        actions.add(pause);
        actions.add(stop);
        actions.add(exit);
        actions.add(checkbox);
        actions.add(current);
        details.add(id);
        details.add(id_val);
        details.add(coordinates);
        details.add(coordinates_val);
        details.add(energy);
        details.add(energy_val);
        details.add(category);
        details.add(category_val);
        details.add(nodesInCategory);
        details.add(nodesInCategory_val);
        details.add(mobile);
        details.add(mobile_val);
        details.add(antRadiatedPower);
        details.add(antRadiatedPower_val);
        details.add(antActivationThreshold);
        details.add(antActivationThreshold_val);

        getContentPane().add(canvas, BorderLayout.CENTER);
        getContentPane().add(actions, BorderLayout.SOUTH);
        //----------------------------------------------------------------------



        //----------------------------------------------------------------------

        setSize(canvas.getSize());
        int x = (int) (screensize.getWidth() - getWidth()) / 2;
        int y = (int) (screensize.getHeight() - getHeight()) / 2;
        setLocation(x, y);
        setVisible(true);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
}
